/**
 * Copyright (c) 2009-2012 XTEAM
 * All rights reserved.
 */
/**
 * File：ConfigManager.java
 * History:
 *         2012-6-18: Initially created, Chrise.
 */
package com.xteam.ecsystem.system;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.caucho.hessian.client.HessianProxyFactory;
import com.xteam.ecsystem.base.NormalState;
import com.xteam.ecsystem.base.SyncObject;
import com.xteam.ecsystem.base.SyncType;
import com.xteam.ecsystem.base.WebService;
import com.xteam.ecsystem.dao.IReqCfgDao;
import com.xteam.ecsystem.dao.ISysCfgDao;
import com.xteam.ecsystem.dao.ISysServerCfgDao;
import com.xteam.ecsystem.dao.ISysWebCfgDao;
import com.xteam.ecsystem.entities.SysRequestConfig;
import com.xteam.ecsystem.entities.SysServerConfig;
import com.xteam.ecsystem.entities.SysSystemConfig;
import com.xteam.ecsystem.entities.SysWebConfig;
import com.xteam.ecsystem.remote.IRemote;
import com.xteam.ecsystem.utils.AppConfig;

/**
 * 配置管理器。
 * @author Chrise
 */
@Service
public class ConfigManager {
	
	// 系统配置
	@Autowired
	private ISysCfgDao scDao;
	
	// 请求配置
	@Autowired
	private IReqCfgDao rcDao;
	
	// 前端配置
	@Autowired
	private ISysWebCfgDao webDao;
	
	// 服务端配置
	@Autowired
	private ISysServerCfgDao serverDao;
	
	private Map<String, IRemote> rService;
	private SysSystemConfig sysConfig;
	private Map<String, SysRequestConfig> reqConfig;
	private SysWebConfig webConfig;
	private SysServerConfig serverConfig;
	
	private static final Log LOG = LogFactory.getLog(ConfigManager.class);
	
	/**
	 * 初始化配置管理器。
	 * @author Chrise 2012-6-18
	 */
	@PostConstruct
	public void initialize() {
		try {
			if (AppConfig.isRemoteSync()) {
				this.rService = new HashMap<String, IRemote>();
				
				List<WebService> webServices = AppConfig.getSyncWebService();
				if (!webServices.isEmpty()) {
					HessianProxyFactory hpf = new HessianProxyFactory();
					for (WebService ws : webServices) {
						IRemote remote = (IRemote)hpf.create(IRemote.class, ws.getAddress());
						if (remote != null) {
							this.rService.put(ws.getAddress(), remote);
						}
					}
				}
			} else {
				String error = null;
				
				error = this.localLoadForSysCfg();
				if (error != null) {
					if ("".equals(error)) error = "当前未加载任何系统配置！";
					
					LOG.error(error);
				}
				
				error = this.localLoadForReqCfg();
				if (error != null) {
					if ("".equals(error)) error = "当前未加载任何请求配置！";
					
					LOG.error(error);
				}
				
				error = this.localLoadForWebCfg();
				if (error != null) {
					if ("".equals(error)) error = "当前未加载任何前端配置！";
					
					LOG.error(error);
				}
			}
			
			this.serverConfig = this.serverDao.getSysServerCfg();
			
		} catch (Exception e) {
			LOG.error("初始化配置管理器失败：" + e.getMessage());
		}
	}
	
	/**
	 * 获取系统配置。
	 * @author Chrise 2012-6-18
	 * @return
	 */
	public SysSystemConfig getSystemConfig() {
		return this.sysConfig;
	}
	
	/**
	 * 获取请求配置。
	 * @author Chrise 2012-6-18
	 * @param request
	 * @return
	 */
	public SysRequestConfig getRequestConfig(String request) {
		if (this.reqConfig == null || !this.reqConfig.containsKey(request)) return null;
		
		return this.reqConfig.get(request);
	}
	
	/**
	 * 获取前端配置。
	 * @author Chrise 2012-6-18
	 * @return
	 */
	public SysWebConfig getWebConfig() {
		return this.webConfig;
	}
	
	/**
	 * 获得服务端配置
	 * @author liuzhi 2013-12-24
	 * @return
	 */
	public SysServerConfig getServerConfig(){
		return this.serverConfig;
	}
	
	/**
	 * 获取同步对象。
	 * @author Chrise 2012-6-18
	 * @return
	 */
	public SyncObject getSyncObject() {
		if (AppConfig.isRemoteSync()) {
			return new SyncObject(true, AppConfig.getSyncWebService());
		}
		
		List<WebService> list = new ArrayList<WebService>();
		list.add(new WebService("", "localhost"));
		return new SyncObject(false, list);
	}
	
	/**
	 * 同步设置。
	 * @author Chrise 2012-6-18
	 * @param type
	 * @param service
	 * @return
	 */
	public String syncSetting(int type, String service) {
		SyncType st = SyncType.valueOf(type);
		
		switch (st) {
			case SYSCFG:
				return this.syncSystemConfig(service);
			case REQCFG:
				return this.syncRequestConfig(service);
			case WEBCFG:
				return this.syncWebConfig(service);
			default:
				return "非法的同步类型！";
		}
	}
	
	/**
	 * 同步系统配置。
	 * @author Chrise 2012-6-18
	 * @param service
	 * @return
	 */
	public String syncSystemConfig(String service) {
		String error = null;
		
		if (AppConfig.isRemoteSync()) {
			error = this.remoteLoadForSysCfg(service);
		} else {
			error = this.localLoadForSysCfg();
		}
		
		if (error == null) {
			error = "同步设置成功！";
		} else if ("".equals(error)) {
			error = "同步设置成功，当前未加载任何系统配置！";
		}
		
		return error;
	}
	
	/**
	 * 同步请求配置。
	 * @author Chrise 2012-6-18
	 * @param service
	 * @return
	 */
	public String syncRequestConfig(String service) {
		String error = null;
		
		if (AppConfig.isRemoteSync()) {
			error = this.remoteLoadForReqCfg(service);
		} else {
			error = this.localLoadForReqCfg();
		}
		
		if (error == null) {
			error = "同步设置成功！";
		} else if ("".equals(error)) {
			error = "同步设置成功，当前未加载任何请求配置！";
		}
		
		return error;
	}
	
	/**
	 * 同步前端配置
	 * @author liuzhi 2013-12-23
	 * @param service
	 * @return
	 */
	public String syncWebConfig(String service) {
		String error = null;
		
		if (AppConfig.isRemoteSync()) {
			error = this.remoteLoadForWebCfg(service);
		} else {
			error = this.localLoadForWebCfg();
		}
		
		if (error == null) {
			error = "同步设置成功！";
		} else if ("".equals(error)) {
			error = "同步设置成功，当前未加载任何前端配置！";
		}
		
		return error;
	}
	
	/**
	 * 本地加载系统配置。
	 * @author Chrise 2012-6-18
	 * @return
	 */
	private String localLoadForSysCfg() {
		List<SysSystemConfig> list = this.scDao.getConfigsByState(NormalState.EFFECTIVE.value());
		if (list == null) return "读取系统配置项数据失败！";
		if (list.size() > 1) return "不确定的系统配置项！";
		
		this.sysConfig = null;
		
		if (list.isEmpty()) return "";
		
		this.sysConfig = list.get(0);
		
		return null;
	}
	
	/**
	 * 远程加载系统配置。
	 * @author Chrise 2012-6-18
	 * @param service
	 * @return
	 */
	private String remoteLoadForSysCfg(String service) {
		IRemote remote = this.rService.get(service);
		if (remote == null) {
			return "远程服务不存在！";
		}
		
		return remote.syncSystemConfig();
	}
	
	/**
	 * 本地加载请求配置。
	 * @author Chrise 2012-6-18
	 * @return
	 */
	private String localLoadForReqCfg() {
		List<SysRequestConfig> list = this.rcDao.getConfigsByState(NormalState.EFFECTIVE.value());
		if (list == null) return "读取请求配置项数据失败！";
		
		if (this.reqConfig == null) {
			this.reqConfig = new ConcurrentHashMap<String, SysRequestConfig>();
		} else {
			this.reqConfig.clear();
		}
		
		if (list.isEmpty()) return "";
		
		for (SysRequestConfig src : list) {
			String key = src.getSrcRelative().substring(1) + src.getSrcRequest();
			this.reqConfig.put(key, src);
		}
		
		return null;
	}
	
	/**
	 * 远程加载请求配置。
	 * @author Chrise 2012-6-18
	 * @param service
	 * @return
	 */
	private String remoteLoadForReqCfg(String service) {
		IRemote remote = this.rService.get(service);
		if (remote == null) {
			return "远程服务不存在！";
		}
		
		return remote.syncRequestConfig();
	}
	
	/**
	 * 本地加载前端配置
	 * @author liuzhi 2013-12-23
	 * @return
	 */
	private String localLoadForWebCfg() {
		SysWebConfig webConfig = this.webDao.getSysWebCfg();
		if(webConfig == null) {
			return "读取前端配置项数据失败！";
		}
		
		this.webConfig = webConfig;
		
		return null;
	}
	
	/**
	 * 远程加载前端配置
	 * @author liuzhi 2013-12-23
	 * @param service
	 * @return
	 */
	private String remoteLoadForWebCfg(String service) {
		IRemote remote = this.rService.get(service);
		if (remote == null) {
			return "远程服务不存在！";
		}
		
		return remote.syncWebConfig();
	}
}
